<?php

namespace app\devices\service;

use app\wechat\service\WechatService;
use think\admin\extend\CodeExtend;
use think\admin\Service;
use think\cache\driver\Redis;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\facade\Log;

/**
 * 订单数据服务
 * Class OrderService
 * @package app\data\service
 */
class OrderService extends Service
{
    protected $table = 'jcg_devices_order';
    protected $order_status = [1=>'使用中', 2=>'已完成', '3'=>'商户结束'];
    public $special_store = [49];

    /**
     * 获取订单记录
     * @param $map
     * @return \think\Collection
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getList($map){
        return $this->app->db->name($this->table)->where($map)->order('id ASC')->select();
    }

    /**
     * 绑定订单详情数据
     * @param array $data
     * @param $status
     * @param string $mobile
     */
    public function buildItemData(array &$data = [], $status, $mobile='')
    {
        if($data) {
            $o_ids= array_column($data, 'id');
            $codes = DevicesService::instance()->getPickUpCodes($o_ids);

            $s_ids = array_column($data, 'store_id');
            $fee_summarys = $this->app->db->name("jcg_device_fee")->where("store_id", "in", $s_ids)->column("summary", "store_id");

            foreach ($data as &$row){
                $extend = json_decode($row['extends'], true);
                $row['order_id'] = $row['id'];
                $row['box_num'] = isset($extend['box_num']) && $extend['box_num']<10?"0".$extend['box_num']:($extend['box_num']??'');
                $row['dates'] = $row['create_time']?date("Y-m-d H:i",$row['create_time']):$row['create_at'];
                $row['store_name'] = $extend['device_name']??'';
                $row['mobile'] = $codes[$row['id']]['mobile']??'';
                $row['pick_up_code'] = $codes[$row['id']]['code']??0;
                $row['box_type'] = $extend['box_type']??'';
                $row['contact_phone'] = $extend['contact_phone']??'';

                if($row['fee_type']==3){
                    $re_amount = (ceil((time()-$row['create_time']-$row['free_hours']*3600)/3600))*$row['amount'];
                    $re_amount = $re_amount>0?$re_amount:0;
                    if(in_array($row['store_id'], OrderService::instance()->special_store) && $re_amount){
                        $re_amount = $re_amount<2?2:$re_amount;
                    }
                    $max_money = $extend['max_money']??0;

                    $re_amount = $re_amount>$max_money?$max_money:$re_amount;
                    if($row['money']<$re_amount){
                        $row['use_money'] = $row['money'];
                        $row['out_money'] = $re_amount<$max_money?$re_amount-$row['money']:$max_money-$row['money'];
                        $row['balance'] = 0;
                    }else{
                        $row['out_money'] = 0;
                        $row['balance'] = $row['money']-$re_amount;
                        $row['use_money'] = $re_amount;
                    }
                    $row['fee_take_detail'] = $fee_summarys[$row['store_id']]??'';

                    $row['out_money'] = sprintf('%.2f', $row['out_money']);
                    $row['balance'] = sprintf('%.2f', $row['balance']);
                }

                $end_time = $row['reality_end_time'] ? $row['reality_end_time'] : time();

                $row['create_time'] = $row['create_time']?$row['create_time']:strtotime($row['create_at']);

                $use_time = $min = ceil(($end_time - $row['create_time'])/60);
                if($min>60){
                    $hour = intval($min/60);
                    if($hour>24){
                        $use_time = intval($hour/24).'天'.intval($hour%24).'小时'.intval($min%60).'分钟';
                    }else{
                        $use_time = $hour.'小时'.intval($min%60).'分钟';
                    }
                }else{
                    $use_time .= '分钟';
                }

                $row['arrears'] = 0;

                $row['use_time'] = $use_time;

                $row['use_hour'] = sprintf('%.1f',$min/60);

                $row['use_hour'] = $row['use_hour']<0.1?0.1:$row['use_hour'];

                $status = $row['s_id']>0?3:$row['status'];

                $row['status'] = $this->order_status[$status];

                $row['temp_unlock'] = 0;
                if(($extend['half_type']??0)==1 && $row['fee_type']==3){
                    $half_hour = $extend['half_hour']??0;
                    $row['temp_unlock'] = $half_hour<0.1 || $row['create_time']+ceil($half_hour*3600)>time()?1:0;
                }else if($row['fee_type']==2 && ($extend['half_type']??0)==1){
                    $half_hour = $extend['half_hour']??0;
                    $half_hour = $half_hour<0.1?1:$half_hour;
                    $row['temp_unlock'] = $row['create_time']+ceil($half_hour*3600)>time()?1:0;
                }

                if($row['out_times']){
                    $row['status'] = '已超时';
                }

                unset($row['amount'], $row['free_hours'], $row['create_time'], $row['reality_end_time'], $row['extends'], $row['id'], $row['create_at']);
            }
        }
    }

    /**
     * 绑定订单详情数据
     * @param array $data
     * @param $status
     * @param string $mobile
     */
    public function buildOrderList(array &$data = [])
    {
        if($data) {
            $o_ids= array_column($data, 'id');
            $codes = DevicesService::instance()->getPickUpCodes($o_ids);
            $users = $this->app->db->name("data_user")->where("id", "in", array_column($data, 'user_id'))->column("nickname,phone", 'id');
            foreach ($data as &$row){
                $extend = json_decode($row['extends'], true);
                $row['order_id'] = $row['id'];
                $row['box_num'] = isset($extend['box_num']) && $extend['box_num']<10?"0".$extend['box_num']:($extend['box_num']??'');
                $row['dates'] = date("Y-m-d H:i",$row['create_time']);//. ($row['reality_end_time']?' - '.date("Y-m-d H:i",$row['reality_end_time']):'');
                $row['device_name'] = $extend['device_name']??'';
                $row['mobile'] = $codes[$row['id']]['mobile']??($users[$row['user_id']]['phone']);
                $row['pick_up_code'] = $codes[$row['id']]['code']??0;
                $row['box_type'] = $extend['box_type']??'';
                $row['nickname'] = $users[$row['user_id']]['nickname']??'***';

                $end_time = $row['reality_end_time'] ? $row['reality_end_time'] : time();

                $use_time = $min = ceil(($end_time - $row['create_time'])/60);
                if($min>60){
                    $hour = intval($min/60);
                    if($hour>24){
                        $use_time = intval($hour/24).'天'.intval($hour%24).'小时'.intval($min%60).'分钟';
                    }else{
                        $use_time = $hour.'小时'.intval($min%60).'分钟';
                    }
                }else{
                    $use_time .= '分钟';
                }
                $row['status'] = $row['out_times'] && $row['status']==1?3:$row['status'];

                $row['use_time'] = $use_time;

                unset($row['create_time'], $row['reality_end_time'], $row['extends'], $row['id'], $row['user_id'], $row['s_id']);
            }
        }
    }

    /**
     * 获取订单信息
     * @param string $orderNo 订单号
     * @param array $map 其它更新条件
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function get(string $orderNo='', array $map=[])
    {
        $where = [];
        if($orderNo) $where['order_no'] = $orderNo;
        return $this->app->db->name($this->table)->where($where)->where($map)->find();
    }

    public function endOrder($id, $data){
        return $this->app->db->name($this->table)->where("id", $id)->update($data);
    }

    /**
     * 获取缓存订单信息
     * @param $id
     * @return array|\think\Model|null
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\DbException
     * @throws \think\db\exception\ModelNotFoundException
     */
    public function getCacheOrder($id){
        $redis = new Redis();
        $order = $redis->get("CacheOrder".$id);
        if(!$order){
            $order = $this->app->db->name($this->table)->where("id", $id)->find();
        }
        return $order;
    }

    /**
     * 获取正在使用的柜子数量
     * @param $user_id
     * @return int
     */
    public function getOrderNum($user_id){
        $map = ['user_id'=>$user_id, 'status'=>1];
        return $this->app->db->name($this->table)->where($map)->count();
    }

    /**
     * 获取柜子超时订单
     * @param $map
     * @return mixed
     */
    public function getOutTimeNum($map){
        return $this->app->db->name($this->table)->where($map)->group("d_id")->column("count(id) as num", 'd_id');
    }

    /**
     * 获取进行中的订单并标记超时超时
     * @param $map
     * @param $end_time
     * @return array
     */
    public function getOutTimeOrderBoxId($map){
        $field = "id, create_time, user_id, device_board, board_channel, out_times as out_time";
        return $this->app->db->name($this->table)->where($map)->column($field, 'box_id');
    }

    /**
     * 删除超时定时任务对应订单缓存
     * @param $order
     */
    public function clearOutTimeOrderCache($order){
        $redis = new Redis();
        $redis_pushs = $redis->get("PushTimeOutOrder");
        if(isset($redis_pushs[$order['user_id']])){
            $m_push = [];
            foreach ($redis_pushs as $user_id=>$row){
                if($user_id==$order['user_id']){
                    foreach ($row as $key=>$val){
                        if($val['order_id']!=$order['id']) {
                            $m_push[$user_id][] = $val;
                        }
                    }
                }else{
                    $m_push[$user_id] = $row;
                }
            }
            $redis->delete("PushTimeOutOrder");
            if($m_push) $redis->set("PushTimeOutOrder", $m_push, 60*60);
        }
    }

    /**
     * 获取订单数据信息
     * @param $store_ids
     * @param $times
     * @param $is_cache
     * @return array|\think\Model|null
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    public function getInfos($store_ids, $times, $is_cache=false){
        $map = [
            ['status','=',2],
            ['store_id','in',$store_ids],
            ['create_at', "between", $times]
        ];

//        $fields = "DATE(create_at) as time, GROUP_CONCAT(CONCAT_WS('_',fee_type,amount_total,money,share_ratio,DAY(create_at))) as info, COUNT(IF(status>0,id,NULL)) as num";
//
//        $list = $this->app->db->name($this->table)->where($map)->cache($is_cache)->fieldRaw($fields)->group('store_id, time')->select()->toArray();

        $subSql = $this->app->db->name("JcgDevicesOrder")->where($map)->field("id, store_id, IF(fee_type=3,amount_total,money) as amount_a")->buildSql();

        $list = Db::query("SELECT store_id, COUNT(IF(amount_a>0,id,NULL)) as num, sum(amount_a) as total FROM {$subSql} a GROUP BY store_id");

        $totals = $num = 0;
        foreach ($list as $row){
            $num +=$row['num'];
            $totals +=$row['total'];
        }

        $info['totals'] = sprintf("%.2f",$totals);
        $info['num'] = $num;

        return $info;
    }

    public function getRefund($order){
        if($order['fee_type']==3){
            $redis = new Redis();
            $refund = $redis->get("OutOrder".$order['id']);
            if($refund){
                return $refund;
            }else{
                return $this->app->db->name("jcg_devices_order")->where("pid", $order['id'])->value('id');
            }
        }
    }


    /**
     * 退款
     * @param $order
     * @return array|bool
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     */
    public function refund($order){
        if($order['fee_type']==3){
            $weChatPay = WechatService::WeChatPay();

            $out_refund_no = CodeExtend::uniqidDate(18, 'F');
            $refund_desc = '使用时间少于订单预付款可使用时间，退还剩余押金';

            $appid = sysconf('wechat.appid')??'';
            if($appid=='wx0d7d455b9edc9ada'){
                $order['money'] = 0.01;
                $order['refund'] = 0.01;
            }

            $option = [
                'transaction_id'=>$order['trade_no'],
                'out_refund_no'=>$out_refund_no,
                'refund_desc'=>$refund_desc,
                'total_fee'=>$order['money']*100,
                'refund_fee'=>$order['refund']*100,
            ];

            $info = $weChatPay->createRefund($option);
            if($info['return_code']=='SUCCESS' && $info['result_code']=='SUCCESS'){
                return [
                    'out_refund_no'=>$out_refund_no,
                    'err_code_des'=>'',
                    'statsu'=>1,
                ];
            }else{
                return [
                    'out_refund_no'=>'',
                    'err_code_des'=>$info['err_code_des'],
                    'statsu'=>0,
                ];
            }
        }else{
            return true;
        }
    }

    /**
     * 发送微信公众号模板消息
     * @param $type
     * @param $openid
     * @param $data
     * @param string $f_title
     * @param string $r_title
     * @throws \WeChat\Exceptions\InvalidResponseException
     * @throws \WeChat\Exceptions\LocalCacheException
     */
    public function sendTemp($type, $openid, $data, $f_title="", $r_title=""){
        $wechat = WechatService::WeChatTemplate();

        $appid = $customer = "";
        if(stripos($openid,"+_+")){
            $infos = explode("+_+", $openid);
            list($openid, $appid) = $infos;
            $customer = $appid;
        }

        $appid = $appid?$appid:sysconf("wechat.appid");

        if($appid=='wx0d7d455b9edc9ada'){
            $template_ids = [
                '4'=>'xBMbLjHQC8jyfa3vVbYDVNbVY_IFtvtMMGYL24a-RQ8',
                '3'=>'0FyrYM845l1tinTUuc9eTAlrATY3vr4_ON6wAk4p7IQ',
                '2'=>'aIxRPfBYZwErJXic_Knc4_sF4AGTQw_yftV-2gHdvyA',
                '1'=>'sgeJB7dP_8A0aqwUjLKAa-p1LZgBb51Mha0RjepXCQs',
            ];
        }else if($appid=="wx484d58740cc35f49"){
            //客户三渡
            $template_ids = [
                '4'=>'o1w3Hay6CiLrHMML8Y8OCr3-TvNsYhKr4osplt1upEU', //柜门未关提醒
                '3'=>'DM39J30OVJw7X_9iJOzBxRlRyFTu0VTqoN6q0jHu2kE', //储物柜快到期提醒
                '2'=>'byKF1KHfFshTf03Akp0UEJ4DGWRv-saRnWq32r5PKh4', //寄存结束通知
                '1'=>'0w897HfSr0F-rtuZdjchaTHl8ns0-PP-hLMIZWKoh_8', //寄存成功通知
            ];
        }else{
            $template_ids = [
                '4'=>'QhdxvMkh8srTZTD-PTswpZW01bHVErPc6uwQnN4iF5I',
                '3'=>'sMdeYE8AqnmlHvb-f1sbmKcHOipEBc_SKMyQGsZHFT4',
                '2'=>'RkCbMju-_vT9rZbI7DhUr18katP3KWUROQT0VNxKUTA',
                '1'=>'7YazasS_njsME46_DYdC0_nUX6cgqGzpcDPf4XcHKkU',
            ];
        }
        $template_id = $template_ids[$type??1];

        switch ($type){
            case 4:
                $first['value'] = $f_title?$f_title:'您的柜门尚未关闭，请关好柜门';
                $remark['value'] = $r_title?$r_title:'感谢您的配合！';
                break;
            case 3:
                $first['value'] = $f_title?$f_title:'您好，您的寄存柜订单还有30分钟到期，请及时取出物品。';
                $remark['value'] = $r_title?$r_title:'请在规定的营业时间内取包，超时请联系客服';
                break;
            case 2:
                $first['value'] = $f_title?$f_title:'物品寄存已结束';
                $remark['value'] = $r_title?$r_title:'感谢您的使用！';
                break;
            case 1:
            default:
                $first['value'] = $f_title?$f_title:'物品寄存成功，欢迎使用豪达智能储物柜';
                $remark['value'] = $r_title?$r_title:'请在营业时间内取包，如有疑问，请联系客服';
                break;
        }

        $temp_data = [
            'touser'=>$openid,
            'template_id' => $template_id,
            'appid' => '',
            'data'=>[
                'first'=> $first,
                'remark'=> $remark,
            ]
        ];

        foreach ($data as $key=>$row){
            $temp_data['data']['keyword'.($key+1)] = ['value'=>$row];
        }

        $wechat->send($temp_data, $customer);
    }
}